package com.ruoyi.framework.config;

import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.connection.ConnectionPoolSettings;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.properties.MongoProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.MongoTransactionManager;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 功能描述: <br>
 * 〈〉
 *
 * @Author gankench@gmail.com
 * @Description //TODO 3:32 PM
 * @Date 3:32 PM 3/23/21
 * @Param
 * @return
 **/
@Configuration
public class MongoConfig {
    @Autowired
    MongoProperties mongoProperties;

    @Bean("mongoTemplate")
    public MongoTemplate getMongoTemplate(@Qualifier("mongoDbFactory") MongoDbFactory dbFactory,
                                          @Qualifier("mappingMongoConverter") MappingMongoConverter converter) {
        return new MongoTemplate(dbFactory, converter);
    }

    @Bean("gridFsTemplate")
    public GridFsTemplate gridFsTemplate(@Qualifier("mongoDbFactory") MongoDbFactory dbFactory,
                                         @Qualifier("mappingMongoConverter") MappingMongoConverter converter) {
        return new GridFsTemplate(dbFactory, converter);
    }

    @Bean("mongoMappingContext")
    public MongoMappingContext mongoMappingContext() {
        MongoMappingContext mappingContext = new MongoMappingContext();
        return mappingContext;
    }

    @Bean("mappingMongoConverter")
    public MappingMongoConverter mappingMongoConverter(@Qualifier("mongoDbFactory") MongoDbFactory factory,
                                                       @Qualifier("mongoMappingContext") MongoMappingContext context) {
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
        MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
        //去掉默认mapper添加的_class
        mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
        return mappingConverter;
    }

    @Bean
    public MongoTransactionManager transactionManager(@Qualifier("mongoDbFactory") MongoDbFactory dbFactory) {
        return new MongoTransactionManager(dbFactory);
    }

    @Bean(name = "mongoDbFactory")
    public MongoDbFactory mongoDbFactory() {
        List<ServerAddress> serverAddressList = new ArrayList<>();

        for (String s : mongoProperties.getAddress()) {
            String host = s.substring(0, s.lastIndexOf(":"));
            String port = s.substring(s.lastIndexOf(":") + 1);
            serverAddressList.add(new ServerAddress(host, Integer.parseInt(port)));
        }

        // 连接认证，如果设置了用户名和密码的话
        MongoClientSettings settings = null;
        ConnectionPoolSettings poolSetting = ConnectionPoolSettings.builder().
                maxWaitTime(mongoProperties.getMaxWaitTime(), TimeUnit.MILLISECONDS).build();
        if (StringUtils.isNotBlank(mongoProperties.getUserName())) {
            MongoCredential credential = MongoCredential.createScramSha1Credential(mongoProperties.getUserName(),
                    mongoProperties.getAuthDB(), mongoProperties.getPassword().toCharArray());
            settings = MongoClientSettings.builder()
                    .credential(credential)
                    .applyToConnectionPoolSettings(builder -> builder.applySettings(poolSetting))
                    .applyToClusterSettings(builder -> builder.hosts(serverAddressList)).build();
        } else {
            settings = MongoClientSettings.builder().applyToConnectionPoolSettings(builder -> builder.applySettings(poolSetting))
                    .applyToClusterSettings(builder -> builder.hosts(serverAddressList)).build();
        }

        MongoClient mongoClient = MongoClients.create(settings);
        // 创建MongoDbFactory
        SimpleMongoClientDbFactory factory = new SimpleMongoClientDbFactory(mongoClient,
                mongoProperties.getDatabase());
        return factory;

    }
}